# -*- coding=utf-8 -*-
import time
import RPi.GPIO as gpio


def getCPUTemp()->float:
    try:
        with open("/sys/class/thermal/thermal_zone0/temp") as temp_file:
            temp=temp_file.readline()
        return float(temp)/1e3  # e.g. temp='23849' -> 23.849
    except (ValueError,FileNotFoundError,OSError) as error:
        raise error


class SmartFan:
    # 适用于单线程的单例模式
    _instance=None

    def __init__(self,pin=8):
        # 设定默认使用的gpio针脚为8号物理针脚
        self._pin=pin
        # CPU内核达到设定的最高温度后开启风扇散热
        self._htemp=50
        # CPU内核降至设定的最低温度后关闭散热风扇
        self._ltemp=35
        # 脚本监测CPU内核温度的时间监测，单位秒
        self._interval=30
        # 设定默认风扇状态为关闭状态
        self._fanoff=True
        # 设定gpio针脚编程模式
        gpio.setmode(gpio.BOARD)
        # 忽略因自定义针脚编程引起的警告信息
        gpio.setwarnings(False)
        # 初始化默认针脚为输出模式且默认为低电平
        gpio.setup(self._pin,gpio.OUT,initial=gpio.LOW)


    def __new__(cls,*args,**kw):
        if cls._instance is None:
            cls._instance=object.__new__(cls,*args,**kw)
        return cls._instance


    def fanControl(self):
        try:
            while True:
                # 获取当前CPU内核温度
                temp=getCPUTemp()
                # 判断条件启动风扇散热
                if temp>=self._htemp and self._fanoff is True:
                    gpio.output(self._pin,gpio.HIGH)
                    self._fanoff=False
                # 判断条件关闭散热风扇
                elif temp<=self._ltemp and self._fanoff is False:
                    gpio.output(self._pin,gpio.LOW)
                    self._fanoff=True

                # 每隔30s监测决定风扇状态
                time.sleep(self._interval)
        except KeyboardInterrupt:
            print("User has terminated the script!")
        except Exception as error:
            print(error)
        finally:
            # 退出脚本前，清理并释放本次占用的gpio资源
            gpio.cleanup()
            print("Clean up successfully!")


    def setHighTemp(self,htemp:int)->bool:
        if htemp<=self._ltemp:
            return False
        else:
            self._htemp=htemp
            return True


    def setLowTemp(self,ltemp:int)->bool:
        if ltemp>=self._htemp:
            return False
        else:
            self._ltemp=ltemp
            return True

    def setInterval(self,interval:int)->bool:
        if interval<=0:
            return False
        else:
            self._interval=interval
            return True


if __name__=="__main__":
    smartFan=SmartFan()
    smartFan.fanControl()
